﻿using Microsoft.Xna.Framework;
using System;
using Terraria;
using Terraria.Audio;
using Terraria.GameContent.Bestiary;
using Terraria.GameContent.ItemDropRules;
using Terraria.ID;
using Terraria.ModLoader;

namespace MasterMasterMode.Content.NPCs
{
    public class WaterBolt : ModNPC
    {
        private enum AIState
        {
            ChasePlayer,    
            CirclePlayer,   
            StationaryShoot,
            Transition   
        }
        public override void SetBestiary(BestiaryDatabase database, BestiaryEntry bestiaryEntry)
        {
            bestiaryEntry.Info.AddRange([               
                BestiaryDatabaseNPCsPopulator.CommonTags.SpawnConditions.Biomes.TheDungeon,
                new FlavorTextBestiaryInfoElement("Mods.MasterMasterMode.Bestiary.WaterBolt"),
            ]);
        }

        private AIState currentState = AIState.ChasePlayer;
        private int stateTimer = 0;
        private int attackTimer = 0;
        private int shootCounter = 0;
        private readonly float circleRadius = 400f;
        private float circleAngle = 0f;
        private int stateChangeCooldown = 0;
        private Vector2 stationaryPosition = Vector2.Zero;

        public override void SetStaticDefaults()
        {
            Main.npcFrameCount[Type] = 1;
        }

        public override void SetDefaults()
        {
            NPC.width = 32;
            NPC.height = 32;
            NPC.lifeMax = 100;
            NPC.damage = 20;
            NPC.defense = 15;
            NPC.knockBackResist = 0f;
            NPC.noGravity = true;
            NPC.noTileCollide = true;
            NPC.HitSound = SoundID.NPCHit5;
            NPC.DeathSound = SoundID.NPCDeath7;
            NPC.value = Item.buyPrice(0, 0, 45, 0);
            NPC.aiStyle = -1;
        }

        public override void AI()
        {
            NPC.TargetClosest();
            Player player = Main.player[NPC.target];

            if (!player.active || player.dead)
            {
                NPC.velocity *= 0.95f;
                if (NPC.velocity.Length() < 0.1f)
                    NPC.velocity = Vector2.Zero;
                return;
            }

            if (stateChangeCooldown > 0)
                stateChangeCooldown--;

            switch (currentState)
            {
                case AIState.ChasePlayer:
                    ChasePlayerAI(player);
                    break;

                case AIState.CirclePlayer:
                    CirclePlayerAI(player);
                    break;

                case AIState.StationaryShoot:
                    StationaryShootAI(player);
                    break;

                case AIState.Transition:
                    TransitionAI(player);
                    break;
            }

            stateTimer++;
            attackTimer++;
            if (stateChangeCooldown == 0)
            {
                if (currentState == AIState.ChasePlayer && stateTimer > 180)
                {
                    ChooseNextState();
                }
                else if (currentState == AIState.CirclePlayer && stateTimer > 240)
                {
                    ChooseNextState();
                }
                else if (currentState == AIState.StationaryShoot && stateTimer > 200)
                {
                    currentState = AIState.Transition;
                    stateTimer = 0;
                    stateChangeCooldown = 60;
                }
            }

            if (NPC.velocity.Length() > 0.1f)
            {
                NPC.rotation = NPC.velocity.ToRotation() + MathHelper.PiOver2;
            }
            else if (currentState == AIState.StationaryShoot)
            {
                Vector2 direction = player.Center - NPC.Center;
                NPC.rotation = direction.ToRotation() + MathHelper.PiOver2;
            }
        }

        private void ChooseNextState()
        {
            if (Main.rand.NextFloat() < 0.3f)
            {
                currentState = AIState.StationaryShoot;
            }
            else
            {
                currentState = Main.rand.NextBool() ? AIState.ChasePlayer : AIState.CirclePlayer;
            }

            stateTimer = 0;
            attackTimer = 0;
            shootCounter = 0;
            stateChangeCooldown = 60;
        }

        private void ChasePlayerAI(Player player)
        {
            Vector2 targetPosition = player.Center + new Vector2(0, -200f);
            Vector2 direction = targetPosition - NPC.Center;

            float distance = direction.Length();
            if (distance > 10f)
            {
                direction = direction.SafeNormalize(Vector2.Zero);
                NPC.velocity = Vector2.Lerp(NPC.velocity, direction * 8f, 0.1f);
            }
            else
            {
                NPC.velocity *= 0.95f;
            }

            if (attackTimer > 40)
            {
                ShootWaterBolt(player);
                attackTimer = 0;
            }
        }

        private void CirclePlayerAI(Player player)
        {
            circleAngle += 0.02f;
            if (circleAngle > MathHelper.TwoPi)
                circleAngle -= MathHelper.TwoPi;

            Vector2 targetPosition = player.Center + new Vector2(
                (float)Math.Cos(circleAngle) * circleRadius,
                (float)Math.Sin(circleAngle) * circleRadius
            );

            Vector2 direction = targetPosition - NPC.Center;
            if (direction.Length() > 10f)
            {
                direction = direction.SafeNormalize(Vector2.Zero);
                NPC.velocity = Vector2.Lerp(NPC.velocity, direction * 6f, 0.05f);
            }
            else
            {
                NPC.velocity *= 0.95f;
            }

            if (attackTimer > 60)
            {
                ShootWaterBolt(player);
                attackTimer = 0;
            }
        }

        private void StationaryShootAI(Player player)
        {
            if (stationaryPosition == Vector2.Zero)
            {
                ChooseStationaryPosition(player);
            }
            Vector2 directionToPosition = stationaryPosition - NPC.Center;
            if (directionToPosition.Length() > 20f)
            {
                directionToPosition = directionToPosition.SafeNormalize(Vector2.Zero);
                NPC.velocity = Vector2.Lerp(NPC.velocity, directionToPosition * 5f, 0.1f);
            }
            else
            {
                NPC.velocity *= 0.9f;
                if (attackTimer > 15) 
                {
                    ShootWaterBolt(player);
                    shootCounter++;
                    attackTimer = 0;
                    if (shootCounter >= 8)
                    {
                        shootCounter = 0;
                        attackTimer = -30; 
                    }
                }
            }
        }

        private void ChooseStationaryPosition(Player player)
        {
            bool leftSide = Main.rand.NextBool();
            float xOffset = Main.rand.Next(200, 300); 
            float yOffset = Main.rand.Next(-150, -50); 

            if (leftSide)
            {
                stationaryPosition = player.Center + new Vector2(-xOffset, yOffset);
            }
            else
            {
                stationaryPosition = player.Center + new Vector2(xOffset, yOffset);
            }
        }

        private void TransitionAI(Player player)
        {
            NPC.velocity *= 0.9f;
            stationaryPosition = Vector2.Zero; 

            if (stateTimer > 30)
            {
                ChooseNextState();
                stateTimer = 0;
                circleAngle = (player.Center - NPC.Center).ToRotation();
            }
        }

        private void ShootWaterBolt(Player player)
        {
            Vector2 shootPosition = NPC.Center;
            Vector2 direction = (player.Center - shootPosition).SafeNormalize(Vector2.Zero);
            float accuracy = currentState == AIState.StationaryShoot ? 0.05f : 0.1f;
            direction = direction.RotatedByRandom(accuracy);
            float speed = currentState == AIState.StationaryShoot ? 10f : 12f;
            if (Main.netMode != NetmodeID.MultiplayerClient)
            {
                int projectile = Projectile.NewProjectile(NPC.GetSource_FromAI(), shootPosition, direction * speed, ProjectileID.WaterBolt, NPC.damage / 2, 2f, Main.myPlayer);
                Main.projectile[projectile].friendly = false;
                Main.projectile[projectile].hostile = true;
                Main.projectile[projectile].timeLeft = 300;
                Main.projectile[projectile].rotation = direction.ToRotation();
                for (int i = 0; i < 3; i++)
                {
                    Dust.NewDust(shootPosition, 10, 10, DustID.WaterCandle,
                        direction.X * 2f, direction.Y * 2f, 100, default, 1.5f);
                }
            }
            SoundEngine.PlaySound(SoundID.Item21, shootPosition);
        }

        public override void HitEffect(NPC.HitInfo hit)
        {
            for (int i = 0; i < 5; i++)
            {
                Dust.NewDust(NPC.position, NPC.width, NPC.height, DustID.Water,
                    hit.HitDirection, -1f, 0, default, 1f);
            }
        }

        public override void OnKill()
        {
            for (int i = 0; i < 20; i++)
            {
                Dust.NewDust(NPC.position, NPC.width, NPC.height, DustID.Water,
                    Main.rand.NextFloat(-3f, 3f), Main.rand.NextFloat(-3f, 3f), 0, default, 1.5f);
            }
            SoundEngine.PlaySound(SoundID.Item54, NPC.Center);
        }
        public override void ModifyNPCLoot(NPCLoot npcLoot)
        {
            npcLoot.Add(ItemDropRule.Common(ItemID.WaterBolt, 1, 1, 1));            
        }
    }
}